package com.yhq.thrift.client;

import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.apache.thrift.TException;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * Created by yhq on 2016/12/7.
 */
@Slf4j
public class ThriftProxy<T> implements MethodInterceptor {

    protected String serviceClient;

    protected String serviceName;

    protected Type type;

    protected Type superClass;

    public ThriftProxy(ThriftConnectionFactory thriftConnectionFactory) {
        superClass = this.getClass().getGenericSuperclass();
        type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
        String ifaceName = type.getTypeName();
        serviceName = ifaceName.replaceAll("Iface", "Processor");
        serviceClient = ifaceName.replaceAll("Iface", "Client");
        this.thriftConnectionFactory = thriftConnectionFactory;
    }

    private ThriftConnectionFactory thriftConnectionFactory;

    @Override
    public Object intercept(Object target, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {
        ThriftConnection thriftConnection = thriftConnectionFactory.getConnection(serviceName, serviceClient);
        try {
            Object result = thriftConnection.exec(method, params);
            return result;
        } catch (InvocationTargetException invocation) {
            log.error("调用thrift时,被调用方法抛出异常,异常为:", invocation);
            throw new TException("调用thrift时,被调用方法抛出异常");
        } catch (Exception e) {
            log.error("调用thrift发生错误", e);
            throw new TException("调用thrift失败");
        } finally {
            thriftConnection.close();
        }
    }

    public ThriftConnectionFactory getThriftConnectionFactory() {
        return thriftConnectionFactory;
    }

    public void setThriftConnectionFactory(ThriftConnectionFactory thriftConnectionFactory) {
        this.thriftConnectionFactory = thriftConnectionFactory;
    }

    public T createProxy() throws Exception {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Class.forName(type.getTypeName()));// 设置代理目标
        enhancer.setCallback(this);// 设置回调
        return (T) enhancer.create();
    }
}